import type { GraphicObject } from './GraphicObject';

export interface HistoryAction {
  type: string;
  data: any;
  timestamp: number;
}

export interface ObjectState {
  id: string;
  transform: any;
  style: any;
  layerId: string;
}

export class HistoryManager {
  private undoStack: HistoryAction[] = [];
  private redoStack: HistoryAction[] = [];
  private maxHistorySize: number = 100;
  private isRecording: boolean = true;

  /**
   * 记录对象创建
   */
  recordObjectCreated(object: GraphicObject): void {
    if (!this.isRecording) return;

    const action: HistoryAction = {
      type: 'object_created',
      data: {
        objectId: object.id,
        objectData: object.serialize(),
      },
      timestamp: Date.now(),
    };

    this.pushToUndoStack(action);
    this.clearRedoStack();
  }

  /**
   * 记录对象删除
   */
  recordObjectDeleted(object: GraphicObject): void {
    if (!this.isRecording) return;

    const action: HistoryAction = {
      type: 'object_deleted',
      data: {
        objectId: object.id,
        objectData: object.serialize(),
      },
      timestamp: Date.now(),
    };

    this.pushToUndoStack(action);
    this.clearRedoStack();
  }

  /**
   * 记录对象变换
   */
  recordObjectTransformed(object: GraphicObject, oldTransform: any): void {
    if (!this.isRecording) return;

    const action: HistoryAction = {
      type: 'object_transformed',
      data: {
        objectId: object.id,
        oldTransform: { ...oldTransform },
        newTransform: { ...object.transform },
      },
      timestamp: Date.now(),
    };

    this.pushToUndoStack(action);
    this.clearRedoStack();
  }

  /**
   * 记录对象样式变化
   */
  recordObjectStyled(object: GraphicObject, oldStyle: any): void {
    if (!this.isRecording) return;

    const action: HistoryAction = {
      type: 'object_styled',
      data: {
        objectId: object.id,
        oldStyle: { ...oldStyle },
        newStyle: { ...object.style },
      },
      timestamp: Date.now(),
    };

    this.pushToUndoStack(action);
    this.clearRedoStack();
  }

  /**
   * 记录多对象操作
   */
  recordMultipleObjects(
    actionType: string,
    objects: GraphicObject[],
    oldStates?: ObjectState[],
  ): void {
    if (!this.isRecording) return;

    const action: HistoryAction = {
      type: actionType,
      data: {
        objectIds: objects.map((obj) => obj.id),
        oldStates: oldStates || objects.map((obj) => this.getObjectState(obj)),
        newStates: objects.map((obj) => this.getObjectState(obj)),
      },
      timestamp: Date.now(),
    };

    this.pushToUndoStack(action);
    this.clearRedoStack();
  }

  /**
   * 撤销操作
   */
  undo(objectMap: Map<string, GraphicObject>): boolean {
    if (this.undoStack.length === 0) return false;

    this.isRecording = false;

    const action = this.undoStack.pop()!;
    this.redoStack.push(action);

    this.applyAction(action, objectMap, true);

    this.isRecording = true;
    return true;
  }

  /**
   * 重做操作
   */
  redo(objectMap: Map<string, GraphicObject>): boolean {
    if (this.redoStack.length === 0) return false;

    this.isRecording = false;

    const action = this.redoStack.pop()!;
    this.undoStack.push(action);

    this.applyAction(action, objectMap, false);

    this.isRecording = true;
    return true;
  }

  /**
   * 是否可以撤销
   */
  canUndo(): boolean {
    return this.undoStack.length > 0;
  }

  /**
   * 是否可以重做
   */
  canRedo(): boolean {
    return this.redoStack.length > 0;
  }

  /**
   * 清空历史记录
   */
  clear(): void {
    this.undoStack = [];
    this.redoStack = [];
  }

  /**
   * 设置历史记录大小限制
   */
  setMaxHistorySize(size: number): void {
    this.maxHistorySize = Math.max(1, size);
    this.trimUndoStack();
  }

  /**
   * 获取历史记录信息
   */
  getHistoryInfo(): { undoCount: number; redoCount: number } {
    return {
      undoCount: this.undoStack.length,
      redoCount: this.redoStack.length,
    };
  }

  /**
   * 私有方法
   */

  private pushToUndoStack(action: HistoryAction): void {
    this.undoStack.push(action);
    this.trimUndoStack();
  }

  private clearRedoStack(): void {
    this.redoStack = [];
  }

  private trimUndoStack(): void {
    if (this.undoStack.length > this.maxHistorySize) {
      this.undoStack = this.undoStack.slice(-this.maxHistorySize);
    }
  }

  private getObjectState(object: GraphicObject): ObjectState {
    return {
      id: object.id,
      transform: { ...object.transform },
      style: { ...object.style },
      layerId: object.layerId,
    };
  }

  private applyObjectState(object: GraphicObject, state: ObjectState): void {
    object.transform = { ...state.transform };
    object.style = { ...state.style };
    object.layerId = state.layerId;
  }

  private applyAction(
    action: HistoryAction,
    objectMap: Map<string, GraphicObject>,
    isUndo: boolean,
  ): void {
    switch (action.type) {
      case 'object_created':
        if (isUndo) {
          // 撤销创建：删除对象
          const object = objectMap.get(action.data.objectId);
          if (object) {
            // 在实际应用中，这里应该从World中移除对象
            // 这里只是标记对象为删除状态
            objectMap.delete(action.data.objectId);
          }
        } else {
          // 重做创建：重新创建对象
          // 在实际应用中，这里应该重新创建对象
          // 这里只是重新添加到映射中
          // 注意：实际实现需要根据objectData重新创建对象实例
        }
        break;

      case 'object_deleted':
        if (isUndo) {
          // 撤销删除：重新创建对象
          // 在实际应用中，这里应该重新创建对象
        } else {
          // 重做删除：删除对象
          const object = objectMap.get(action.data.objectId);
          if (object) {
            objectMap.delete(action.data.objectId);
          }
        }
        break;

      case 'object_transformed': {
        const object = objectMap.get(action.data.objectId);
        if (object) {
          if (isUndo) {
            // 撤销变换：恢复到旧状态
            object.transform = { ...action.data.oldTransform };
          } else {
            // 重做变换：应用新状态
            object.transform = { ...action.data.newTransform };
          }
        }
        break;
      }

      case 'object_styled': {
        const styledObject = objectMap.get(action.data.objectId);
        if (styledObject) {
          if (isUndo) {
            // 撤销样式：恢复到旧样式
            styledObject.style = { ...action.data.oldStyle };
          } else {
            // 重做样式：应用新样式
            styledObject.style = { ...action.data.newStyle };
          }
        }
        break;
      }

      case 'multiple_objects_moved':
      case 'multiple_objects_rotated':
      case 'multiple_objects_scaled': {
        const states = isUndo ? action.data.oldStates : action.data.newStates;
        for (const state of states) {
          const multiObject = objectMap.get(state.id);
          if (multiObject) {
            this.applyObjectState(multiObject, state);
          }
        }
        break;
      }
    }
  }

  /**
   * 批量操作支持
   */

  startBatch(): void {
    // 在实际实现中，这里可以开始记录批量操作
    // 暂时简化实现
  }

  endBatch(): void {
    // 在实际实现中，这里可以结束记录批量操作
    // 暂时简化实现
  }

  /**
   * 序列化历史记录
   */
  serialize(): any {
    return {
      undoStack: this.undoStack,
      redoStack: this.redoStack,
      maxHistorySize: this.maxHistorySize,
    };
  }

  /**
   * 从数据反序列化历史记录
   */
  deserialize(data: any): void {
    this.undoStack = data.undoStack || [];
    this.redoStack = data.redoStack || [];
    this.maxHistorySize = data.maxHistorySize || 100;
  }

  /**
   * 销毁历史管理器
   */
  destroy(): void {
    this.clear();
  }
}

export default HistoryManager;
